/*
 * @Author: zhangyang
 * @Date: 2022-02-13 11:23:53
 * @LastEditTime: 2022-02-13 17:01:23
 * @Description: 抖音开放平台，主播管理 -> 主播详情 -> 直播数据 -> 数据详情 爬取
 */
import { sleep, sleepRandomTime } from "~/utils/time";
import { youngExport } from "~/utils/youngExport";

export class ByteDanceGetter_Plus_UV {
  /**
   * 数据集合
   */
  public dataMap = ref<DataItem[]>([]);
  /**
   * 下一页的按钮
   */
  private nextSelector = '.ant-pagination-next';
  /**
   * 按钮禁用类
   */
  private nextSelector_DisabledClass = 'ant-pagination-disabled';
  /**
   * 详情按钮
   */
  private detailBtn = '.button--1gbxb';
  /**
   * 30天 快捷选项按钮
   */
  private recent30 = '.data-panel-filter-item-left--11qks';
  /**
   * 返回按钮
   */
  private backBtn = '.anticon-arrow-left';

  /**
   * 外层表格
   */
  private mainTbody = '.ant-table-tbody';

  /**
   * 主播 uid 昵称
   */
  private nickSelector = '.copy-content--sF96b';
  
  /**
   * 翻页
   */
  async nextPage() {
    const btn = document.querySelector(this.nextSelector);
    // 已经到达最后一页
    if (btn?.classList.contains(this.nextSelector_DisabledClass)) {
      return false;
    }
    (btn as HTMLButtonElement).click();
    await sleepRandomTime(3)
    return true;
  }

  /**
   * 获取主播详细数据
   */
  async getBrdDetail(nick: string, uid: string) {
    const dataArr = new Array<DataItem>();
    const tbody = (document.querySelector(this.mainTbody) as HTMLTableElement).children;
    for (const tr of Array.from(tbody)) {
      const {
        0: dateDiv,
        2: timeDiv,
        5: uvDiv
      } = tr.children;

      const date = dateDiv.innerHTML;
      const time = Math.floor(parseFloat(timeDiv.innerHTML) * 60);
      const uv = uvDiv.innerHTML.match(/\d+/)?.[0] ?? '0';

      dataArr.push({ nick, uid, date, time, uv });
    }
    return dataArr;
  }

  /**
   * 获取每个主播的详细数据
   * 返回上一页会造成之前获取的变量失效，不得已只能使用索引进行遍历
   */
  async getEveryDetail(index: number) {
    const brds = (document.querySelector(this.mainTbody) as HTMLTableElement).children;
    const brd = brds[index];
    console.log(brd)

    const dataArr = new Array<DataItem>();

    const [nickElement, uidElement] = Array.from(brd.querySelectorAll(this.nickSelector)) || [new Element(), new Element()];
    const nick = nickElement?.innerHTML;
    const uid = uidElement?.innerHTML;

    const detailBtn = brd.querySelector(this.detailBtn) as HTMLButtonElement;
    // 进入详情页
    detailBtn.click();
    await sleep(1.5);

    const [_, btn_30] = Array.from(document.querySelectorAll(this.recent30));
    // 获取最近 30 天的数据
    (btn_30 as HTMLElement).click();
    // 时间如果太短会获取不到全部的数据
    await sleep(2);

    do {
      const arr = await this.getBrdDetail(nick, uid);
      dataArr.push(...arr);
      await sleepRandomTime(2);
    } while (await this.nextPage());

    // 返回上一页
    const backBtn = document.querySelector(this.backBtn) as HTMLButtonElement;
    backBtn.click();
    await sleep(6);

    return dataArr;
  }
  /**
   * 获取外层主播数据
   */
  async getBrdInfo() {
    const dataArr = new Array<DataItem>();

    const brds = (document.querySelector(this.mainTbody) as HTMLTableElement).children;
    const len = brds.length;
    for (let index = 0; index < len; index++) {
      const arr = await this.getEveryDetail(index);
      dataArr.push(...arr);
    }
    this.dataMap.value.push(...dataArr);
  }
  async start() {
    const res = window.confirm('为了保证数据的正确性，请确保“入会时间”为升序或降序，点击确认开始爬取');
    if (!res) {
      return;
    }
    do {
      await this.getBrdInfo();
      await sleepRandomTime(3)
    } while (await this.nextPage());
    window.alert('爬取成功，即将下载(编程不易，点击右上角扩展图标可给作者充电)');
    this.exportHandler();
  }

  /**
   * 导出
   */
  async exportHandler() {
    type Head = {
      date: string;
      nick: string;
      uid: string;
      platform: string;
      time: string | number;
      uv: string | number;
    };
    const tableHead: TableHeadItem<Head>[] = [
      { prop: 'date', label: '日期' },
      { prop: 'nick', label: '主播昵称' },
      { prop: 'uid', label: '平台账号' },
      { prop: 'platform', label: '平台' },
      { prop: 'time', label: '直播时长(分钟)' },
      { prop: 'uv', label: 'UV' }
    ];
    const tableData: TableDataItem<Head>[] = [];
  
    for (const { nick, uid, date, time, uv  } of this.dataMap.value) {
      const temp: TableDataItem<Head> = {
        nick,
        uid,
        date,
        time,
        platform: '抖音',
        uv
      };
      tableData.push(temp);
    }
    await youngExport({
      filename: '抖音数据',
      tableHead,
      tableData
    });
    this.clear();
  }

  /**
   * 清空历史记录
   */
  clear() {
    this.dataMap.value.length = 0;
  }
}